#include "./../inc/file.h"
#include "filesystem.h"
#include <string.h>
#include <stdio.h>
#include <memory.h>
#include <stdlib.h>

typedef struct _UFO_File_Internal
{
	HFILE hFile;
	unsigned char *_data;
	int _len;
	int _pos;
	UFO_Handle handle;

}UFO_File_Internal, *PUFO_File_Internal;

UFO_IO ufoIoFromFile(const char *filename)
{
	HFILE hFile = ufoFileOpen(filename, "rb"); 
	if (hFile) {
		PUFO_File_Internal pFile = malloc(sizeof(UFO_File_Internal)) ;
		memset(pFile, 0, sizeof(UFO_File_Internal));
		pFile->hFile = hFile;

		pFile->handle = ufoCreateHandle(UFO_ID_IO, pFile);
		return (UFO_IO)pFile->handle;
	}
	return 0;
}

UFO_IO ufoIoFromMemory(unsigned char *buffer, int length)
{
	if (buffer && length) {
		PUFO_File_Internal pFile = malloc(sizeof(UFO_File_Internal)) ;
		memset(pFile, 0, sizeof(UFO_File_Internal));
		pFile->_data = buffer;
		pFile->_len = length;

		pFile->handle = ufoCreateHandle(UFO_ID_IO, pFile);
		return (UFO_IO)pFile->handle;
	}
	return 0;
}

int ufoIoClose(UFO_IO file)
{
	PUFO_File_Internal pFile = ufoObjectFromHandle((UFO_Handle)file);

	if (pFile)
	{
		if (pFile->hFile)
		{
			ufoFileClose(pFile->hFile);
			pFile->hFile = 0;
		}
		free(pFile);

		ufoCloseHandle((UFO_Handle)file);
	}
	return 1;
}

int ufoIoRead(UFO_IO file, unsigned char *buffer, int size)
{
	PUFO_File_Internal pFile = ufoObjectFromHandle((UFO_Handle)file);

	if (pFile){

		if (pFile->hFile)
		{
			return ufoFileRead(pFile->hFile, buffer, 1, size);
		}
		else if(pFile->_data)
		{
			memcpy(buffer, pFile->_data, size);
			pFile->_pos += size;
			return size;
		}
	}

	return 0;
}

int ufoIoSeek(UFO_IO file, long offset, int origin)
{
	PUFO_File_Internal pFile = ufoObjectFromHandle((UFO_Handle)file);
	if (pFile){
		if (pFile->hFile) {
			return ufoFileSeek(pFile->hFile, offset, origin);//fseek(pFile->_fp, offset, origin);
		}
		else {
			if (origin == SEEK_SET && offset <= pFile->_len)		
				pFile->_pos = offset;
			else if (origin == SEEK_CUR && pFile->_pos+offset <= pFile->_len) 
				pFile->_pos += offset;
			else if (origin == SEEK_END && origin <= 0 && abs(origin) <= pFile->_len) 
				pFile->_pos = pFile->_len + offset;
			else 
				return 0;
		}
		return 1;
	}
	return 0;
}

int ufoIoGetSize(UFO_IO file)
{
	PUFO_File_Internal pFile = ufoObjectFromHandle((UFO_Handle)file);
	if (pFile) {
		int curPos = ufoIoTell(file);
		int nSize = 0;
		ufoIoSeek(file, 0, SEEK_END);
		nSize = ufoIoTell(file);
		ufoIoSeek(file, curPos, SEEK_SET);
		return nSize;
	}
	return 0;
}

int ufoIoTell(UFO_IO file)
{
	PUFO_File_Internal pFile = ufoObjectFromHandle((UFO_Handle)file);
	if (pFile){
		if (pFile->hFile) {
			return ufoFileTell(pFile->hFile);
		}
		else {
			return pFile->_pos;
		}
		return 1;
	}
	return 0;
}
